import {
  Component,
  ComponentFactoryResolver,
  ElementRef,
  Input,
  OnChanges,
  OnInit,
  SimpleChanges,
  ViewChild,
  ViewContainerRef,
} from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { HttpClient } from '@angular/common/http';
import { MessageService } from '@iux/live';
import { I18NService } from '../../../shared';
declare let Prism: any;

export enum CodeTypeEnum {
  HTML = 'html',
  TS = 'ts',
  MODULE = 'module',
}

@Component({
  selector: 'app-example-viewer',
  templateUrl: './example-viewer.component.html',
  styleUrls: ['./example-viewer.component.scss'],
  animations: [
    trigger('viewerState', [
      state('hidden', style({ paddingTop: 0, paddingBottom: 0, height: 0 })),
      state('visible', style({ paddingTop: '*', paddingBottom: '*', height: '*' })),
      transition('visible => hidden', animate('100ms ease-in')),
      transition('hidden => visible', animate('100ms ease-in')),
    ]),
  ],
  host: {
    class: 'example-viewer',
  },
})
export class ExampleViewerComponent implements OnInit, OnChanges {
  @Input() title: string;
  @Input() description: string;
  @Input() innerComponent;
  @Input() baseUrl: string;
  @Input() iframeSrc: string;
  @Input() codeType = [];
  @Input() codePath: string;

  @ViewChild('componentContent', { read: ViewContainerRef, static: true }) componentContent: ViewContainerRef;
  @ViewChild('codePanel') codePanel: ElementRef;

  activeCodeType = CodeTypeEnum.HTML;
  typeOptions: any[] = [
    { label: 'HTML', value: CodeTypeEnum.HTML },
    { label: 'TS', value: CodeTypeEnum.TS },
    { label: 'MODULE', value: CodeTypeEnum.MODULE },
  ];
  codeIdConfig = {
    [CodeTypeEnum.HTML]: 'html-code',
    [CodeTypeEnum.TS]: 'ts-code',
    [CodeTypeEnum.MODULE]: 'module-code',
  };
  htmlCode: any;
  tsCode: any;
  moduleCode: any;

  showCode = false;

  constructor(
    public componentFactoryResolver: ComponentFactoryResolver,
    public el: ElementRef,
    public http: HttpClient,
    public i18n: I18NService,
    private message: MessageService
  ) {}

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.innerComponent) {
      this.codeType.map(type => type.toLowerCase());
      const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.innerComponent);
      this.componentContent.clear();
      this.componentContent.createComponent(componentFactory);
    }
  }

  ngOnInit(): void {}

  appendCodeDom(type: string, codeType: string): void {
    const codePanel = this.codePanel.nativeElement;

    if (!codePanel) {
      return;
    }

    const CodeContent = codePanel.querySelector('.code-content-js');
    const { path, newUrl } = this.getResourceLocation(type, this.codePath);

    if (!newUrl) {
      this.typeOptions.pop();
      return;
    }

    const res = this.http.get(path, { responseType: 'text', params: { $prefix: 'none' } });
    res.subscribe(response => {
      const code = response;
      const html = Prism.highlight(code, codeType);
      CodeContent.innerHTML = html;

      const codeConfig = {
        [CodeTypeEnum.HTML]: () => (this.htmlCode = code),
        [CodeTypeEnum.TS]: () => (this.tsCode = code),
        [CodeTypeEnum.MODULE]: () => (this.moduleCode = code),
      };

      codeConfig[type]();
    });
  }

  toggleCode(event: Event): void {
    event.preventDefault();
    this.showCode = !this.showCode;
    this.appendCodeDom(this.activeCodeType, Prism.languages.html);
  }

  codeTypeChange(e: string): void {
    const config = {
      [CodeTypeEnum.HTML]: Prism.languages.html,
      [CodeTypeEnum.TS]: Prism.languages.js,
      [CodeTypeEnum.MODULE]: Prism.languages.js,
    };

    this.appendCodeDom(e, config[e]);
  }

  // 必须有入参，删除e，功能无法正常使用
  copyCode(e): void {
    const config = {
      [CodeTypeEnum.HTML]: this.htmlCode,
      [CodeTypeEnum.TS]: this.tsCode,
      [CodeTypeEnum.MODULE]: this.moduleCode,
    };

    this.copyToClipboard(config[this.activeCodeType]);
  }

  copyToClipboard(text: string): void {
    const textArea = document.createElement('textarea'); // 创建输入框
    textArea.style.position = 'fixed';
    textArea.style.top = '0';
    textArea.style.left = '0';
    textArea.style.width = '2em';
    textArea.style.height = '2em';
    textArea.style.padding = '0';
    textArea.style.border = 'none';
    textArea.style.outline = 'none';
    textArea.style.boxShadow = 'none';
    textArea.style.background = 'transparent';
    textArea.value = text; // 赋值
    document.body.appendChild(textArea);
    textArea.select(); // 选中

    try {
      const successful = document.execCommand('copy'); // 复制
      if (successful) {
        this.message.success(this.i18n.get('Case_Copy_Successful_ToPaste'));
      } else {
        this.message.error(this.i18n.get('Case_Copy_Fail_ToPaste'));
      }
    } catch (err) {
      this.message.error(this.i18n.get('Case_Copy_Fail_ToPaste'));
    }

    document.body.removeChild(textArea);
  }

  getResourceLocation(type: string, url: string): { [key: string]: string } {
    let path = `${url}.${type}`;
    let newUrl = url;
    if (type === CodeTypeEnum.MODULE) {
      const _url = url.split('.');
      _url.pop();
      newUrl = _url.join('.');
      path = `${newUrl}.module.ts`;
    }
    return { path, newUrl };
  }
}
